package com.zlcx.tz.live.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.RateLimiter;
import com.tencentcloudapi.tiia.v20190529.models.PornResult;
import com.zlcx.tz.live.constant.ComplaintType;
import com.zlcx.tz.live.constant.OpperateState;
import com.zlcx.tz.live.constant.RedisKeyConst;
import com.zlcx.tz.live.constant.dic.CHECK_IMAGE_RATE;
import com.zlcx.tz.live.domain.DicDO;
import com.zlcx.tz.live.domain.LiveComplaint;
import com.zlcx.tz.live.domain.LiveRoomInfo;
import com.zlcx.tz.live.exception.CheckParamException;
import com.zlcx.tz.live.exception.SendExceptionUtil;
import com.zlcx.tz.live.repository.LiveComplaintRepository;
import com.zlcx.tz.live.vo.ComplaintRoomBody;
import com.zlcx.tz.live.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Example;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.zlcx.tz.live.constant.dic.CHECK_IMAGE_RATE.*;
import static com.zlcx.tz.live.vo.UserVO.StatusEnums.LIVE_LEARNING;

/**
 * <p></p>
 * <PRE>
 * <BR>    修改记录
 * <BR>-----------------------------------------------
 * <BR>    修改日期         修改人          修改内容
 * </PRE>
 *
 * @author zl
 * @version 1.0
 * @date Created in 2019/4/18 15:49
 * @copyright: Copyright (c) founders
 */

@Slf4j
@Service
public class LiveComplaintService {

    @Autowired
    LiveComplaintRepository complaintRepository;

    @Autowired
    MessageService messageService;

    @Autowired
    SendExceptionUtil emailService;

    @Value("${swagger.hostname}")
    private String hostname;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    LiveRoomService roomService;

    @Autowired
    UserService userService;

//    @Resource(name = "taskExecutor")
//    AsyncTaskExecutor asyncTaskExecutor;

    @Autowired
    SysConfService sysConfService;

    @Autowired
    private DicServiceImpl dicService;

//    @Autowired
//    private UserDiaryClient userDiaryClient;

    @Autowired
    private AliContentCheckService aliContentCheckService;

    @Autowired
    private UploadService uploadService;

    @Resource(name = "recordExecutor")
    ThreadPoolTaskExecutor recordExecutor;

    @Autowired
    private TencentImageCheckService tencentImageCheckService;

    private Logger traceLoger = LoggerFactory.getLogger("traceloger");

    private static RateLimiter rateLimiter = RateLimiter.create(3);

    public void complaint(Long roomId, Long userId, Integer complaintType, Long complainedUserId, ComplaintRoomBody complaintRoomBody) throws Exception {


        log.info("complaintRoomBody = {} ", JSON.toJSONString(complaintRoomBody));

        if (ComplaintType.getComplaintType(complaintType) == null) {
            throw new CheckParamException("举报类型[" + complaintType + "]不存在!");
        }
        if (userId == null || roomId == null) {
            throw new CheckParamException("参数不正确!");
        }
        if (complainedUserId != null && userId.longValue() == complainedUserId.longValue()) {
            throw new CheckParamException("无效操作!");
        }

        LiveRoomInfo roomInfo = roomService.getRoomInfoById(roomId);
        if (roomInfo == null) {
            log.error("[complaint]房间不存在，roomId={},userId={}", roomId, userId);
            throw new CheckParamException("房间不存在!");
        }

        UserVO userVO = userService.getUserInfo(userId);
        if (userVO == null) {
            log.error("[complaint]用户不存在，roomId={},userId={}", roomId, userId);
            throw new CheckParamException("用户不存在!");
        }
        UserVO complainedUserVO = null;
        if (complainedUserId != null && complainedUserId > 0) {
            complainedUserVO = userService.getUserInfo(complainedUserId);
            if (complainedUserVO == null) {
                log.error("[complaint]被举报的用户不存在，roomId={},complainedUserId={}", roomId, complainedUserId);
                throw new CheckParamException("被举报的用户不存在!");
            }
        }


        //todo 图片鉴黄及检测结果

        Date now = new Date();
        StringBuilder emailMsg = new StringBuilder();
        emailMsg.append("举报人：").append(userVO.getName())
                .append("\r\n举报人ID：").append(userVO.getId())
                .append("\r\n举报人电话：").append(userVO.getPhone() == null ? "" : userVO.getPhone())
                .append("\r\n举报时间：").append(DateFormatUtils.format(now, "yyyy-MM-dd HH:mm:ss"))
                .append("\r\n举报类型：").append(ComplaintType.getComplaintType(complaintType).getTips())
                .append("\r\n房间ID：").append(roomInfo.getId())
                .append("\r\n房间名称：").append(roomInfo.getRoomName())
                .append("\r\n房间创建时间：").append(DateFormatUtils.format(roomInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
        if (complainedUserVO != null) {
            emailMsg.append("\r\n被举报人：").append(complainedUserVO.getName())
                    .append("\r\n被举报人ID：").append(complainedUserVO.getId())
                    .append("\r\n被举报人电话：").append(complainedUserVO.getPhone() == null ? "" : complainedUserVO.getPhone());
        }

        if (complaintRoomBody != null && CollectionUtils.isNotEmpty(complaintRoomBody.getImageUrls())) {
            for (int i = 0; i < complaintRoomBody.getImageUrls().size(); i++) {
                emailMsg.append("\r\n举报图片-").append(i + 1).append("：").append(complaintRoomBody.getImageUrls().get(i));
            }
        }

        String closeurl = "https://{hostname}/tz-live-video/liveRoom/adminCloseRoom/{roomId}/{sign}";
        closeurl = closeurl.replace("{hostname}", hostname).replace("{roomId}", String.valueOf(roomInfo.getId()));
        String sign = UUID.randomUUID().toString() + RandomStringUtils.randomNumeric(8);
        closeurl = closeurl.replace("{sign}", sign);
        emailMsg.append("\r\n点击此链接【直接关闭房间】：").append(closeurl);

        String adminCloseRoomSignKey = RedisKeyConst.getAdminCloseRoomSignKey(roomInfo.getId());
        redisTemplate.opsForValue().set(adminCloseRoomSignKey, sign, 2, TimeUnit.DAYS);

        StringBuilder emsMsg = new StringBuilder();
        //举报({1})环境用户：同桌连麦房间({2})用户名称({3})用户ID({4})被用户({5})举报，原因是({6})，举报图片({7})，请快速处理！回T退订
        ArrayList<String> params = new ArrayList<>();
        params.add(sysConfService.getSysEnv());
        params.add(roomInfo.getRoomName());
        if (complainedUserVO != null) {
            params.add(complainedUserVO.getName());
            params.add("" + complainedUserVO.getId());
        }
        params.add(userVO.getName());
        params.add(ComplaintType.getComplaintType(complaintType).getTips());


        emsMsg.append("举报[").append(sysConfService.getSysEnv()).append("]环境用户：同桌连麦房间[").append(roomInfo.getRoomName())
                .append("]");
        if (complainedUserVO != null) {
            emsMsg.append("用户名称[").append(complainedUserVO.getName()).append("]")
                    .append("用户ID[").append(complainedUserVO.getId()).append("]");
        }
        emsMsg.append("被用户[").append(userVO.getName())
                .append("]举报，原因是[").append(ComplaintType.getComplaintType(complaintType).getTips())
                .append("]，");

        String emailTitle = emsMsg.toString() + "，请快速处理！";

        if (complaintRoomBody != null && CollectionUtils.isNotEmpty(complaintRoomBody.getImageUrls())) {
            for (int i = 0; i < complaintRoomBody.getImageUrls().size(); i++) {
                emsMsg.append("\r\n举报图片-").append(i + 1).append("[").append(complaintRoomBody.getImageUrls().get(i)).append("]");
                if (i == 0) {
                    params.add(complaintRoomBody.getImageUrls().get(i));
                }
            }
        }
        emsMsg.append("，请快速处理！");

        LiveComplaint liveComplaint = new LiveComplaint();
        liveComplaint.setComplaintType(complaintType);
        liveComplaint.setComplainantUserId(userVO.getId());
        liveComplaint.setRoomId(roomInfo.getId());
        liveComplaint.setOpperateState(OpperateState.WaitDeal.getCode());
        liveComplaint.setCreateTime(now);
        liveComplaint.setUpdateTime(now);
        if (complainedUserVO != null) {
            liveComplaint.setComplainedUserId(complainedUserVO.getId());
        }

        complaintRepository.save(liveComplaint);

        emailService.sendEmail(emailTitle, emailMsg.toString());

        messageService.sendEmsMsg(sysConfService.getComplainPhones(), emsMsg.toString(), params);

    }

    public void dealComplaint(Long roomId) {

//        asyncTaskExecutor.execute(() -> {
        LiveComplaint liveComplaint = new LiveComplaint();
        liveComplaint.setRoomId(roomId);
        liveComplaint.setOpperateState(OpperateState.WaitDeal.getCode());

        Example<LiveComplaint> example = Example.of(liveComplaint);
        List<LiveComplaint> list = complaintRepository.findAll(example);
        if (CollectionUtils.isNotEmpty(list)) {
            Date now = new Date();
            for (LiveComplaint complaint : list) {
                complaint.setOpperateState(OpperateState.Dealt.getCode());
                complaint.setUpdateTime(now);
                complaintRepository.save(complaint);
            }
        }
        String adminCloseRoomSignKey = RedisKeyConst.getAdminCloseRoomSignKey(roomId);
        redisTemplate.delete(adminCloseRoomSignKey);
//        });

    }


    public void picCheck(Long roomId, Long userId, MultipartFile file) {

        if (!rateLimiter.tryAcquire(1, TimeUnit.SECONDS)) {
            traceLoger.info("图片检测频次限制未检测：roomid={},userId={}", roomId, userId);
            return;
        }


        String url = uploadService.uploadPublishPicCheck(roomId, userId, file);
        if (StringUtils.isEmpty(url)) {
            log.error("上传图片失败：roomid={},userId={}", roomId, userId);
            traceLoger.info("图片检测上传失败：roomid={},userId={}", roomId, userId);
            return;
        }

        recordExecutor.execute(() -> {

//            AliContentCheckService.ImageCheckResult checkResult = null;
//            try {
//                checkResult = aliContentCheckService.checkOneImage(url);
//            } catch (Exception e) {
//                log.error("图片检测异常:url={},e={}",url,e);
//            }
//            if(checkResult == null || 200 != checkResult.getCode() ){
//                log.error("图片检测结果未知：roomid={},userId={},checkResult={}",roomId,userId,JSON.toJSONString(checkResult));
//                return;
//            }
//
//            if(aliContentCheckService.imageIsNomal(checkResult)){
//                log.info("图片检测结果为正常:roomid={},userId={}",roomId,userId);
//                uploadService.deleteFile(url);
//                return;
//            }
//
            DicDO checkRateDO = dicService.findByCode(CHECK_IMAGE_RATE.dicName());
            int safeTotalDuration = checkRateDO.filter(safe_total_duration.name()).getCode().intValue();
            int safeStartMinute = checkRateDO.filter(safe_start_minute.name()).getCode().intValue();
            UserVO userInfo = userService.getUserInfo(userId);

            if (Objects.isNull(userInfo) || !LIVE_LEARNING.code.equals(userInfo.getStatus()) || Objects.isNull(userInfo.getStartLearnTime())) {
                log.info("用户没有进行连麦或连麦已经结束，不再进行鉴黄 roomId = {} userInfo = {}", roomId, userInfo);
                return;
            }

            if ((System.currentTimeMillis() - userInfo.getStartLearnTime().getTime()) / 1000 / 60 > safeStartMinute) {
                log.info("连麦时长超过" + safeStartMinute + "分钟，不再进行鉴黄 roomId = {} userId = {}", roomId, userId);
                return;
            }

            Integer totalLiveTime = userService.totalLiveTime(userId);
            if (Objects.nonNull(totalLiveTime) && totalLiveTime > safeTotalDuration) {
                log.info("用户总连麦时长超过" + safeTotalDuration + "分钟，不再进行鉴黄 roomId = {} userId = {}", roomId, userId);
                return;
            }

            PornResult pornResult = tencentImageCheckService.checkImg(url);
            if (pornResult == null) {
                traceLoger.info("图片检测tencent未返回结果：roomid={},userId={}", roomId, userId);
                uploadService.deleteFile(url);
                return;
            }
            if (tencentImageCheckService.imageIsNomal(pornResult)) {
                traceLoger.info("图片检测tencent未检测结果为正常：roomid={},userId={}", roomId, userId);
                uploadService.deleteFile(url);
                return;
            }

//            if(aliContentCheckService.imageIsPorn(checkResult)
            if (tencentImageCheckService.imageIsPorn(pornResult)) {
                traceLoger.info("图片检测tencent检测结果为不雅内容，系统踢人：roomid={},userId={},tencentCheckResult={}", roomId, userId, JSON.toJSONString(pornResult));
//                log.info("图片检测结果为不雅内容，系统踢人:roomid={},userId={},checkResult={},tencentCheckResult={}",roomId,userId,JSON.toJSONString(checkResult),JSON.toJSONString(pornResult));
                log.info("图片检测结果为不雅内容，系统踢人:roomid={},userId={},tencentCheckResult={}", roomId, userId, JSON.toJSONString(pornResult));
                roomService.adminKickingUser(userId, "system");

                StringBuilder emailMsg = new StringBuilder();
                emailMsg.append("\r\n房间ID：").append(roomId)
                        .append("\r\n用户ID：").append(userId)
                        .append("\r\n图片：").append(url)
//                        .append("\r\nAli系统判定结果：图片属于 ").append(aliContentCheckService.getLabelMsg(checkResult.getLabel()))
//                        .append(",").append(aliContentCheckService.getSuggestionMsg(checkResult.getSuggestion()))
//                        .append(",概率是").append(checkResult.getRate())
                        .append("\r\nTencent系统判定结果：图片审核结论是 ").append(tencentImageCheckService.getSuggestionMsg(pornResult.getSuggestion()))
                        .append(",概率是").append(pornResult.getConfidence())
                        .append("\r\n系统处理结果：").append("已经踢人")
                        .append("\r\n处理时间：").append(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                emailService.sendEmail("同桌连麦图片检测结果为不雅内容", emailMsg.toString());
                return;
            }

            traceLoger.info("图片检测tencent检测结果系统无法判定，需要人工处理：roomid={},userId={},tencentCheckResult={}", roomId, userId, JSON.toJSONString(pornResult));
//            log.info("系统无法判定图片检测结果，需要人工处理:roomid={},userId={},aliCheckResult={},tencentCheckResult={}",roomId,userId,JSON.toJSONString(checkResult),JSON.toJSONString(pornResult));
            log.info("系统无法判定图片检测结果，需要人工处理:roomid={},userId={},tencentCheckResult={}", roomId, userId, JSON.toJSONString(pornResult));

            String alertTime = RedisKeyConst.getPickCheckAlertTimeKey(roomId, userId);
            if (redisTemplate.opsForValue().get(alertTime) != null) {
                return;
            }

            StringBuilder emailMsg = new StringBuilder();
            emailMsg.append("\r\n房间ID：").append(roomId)
                    .append("\r\n用户ID：").append(userId)
                    .append("\r\n图片：").append(url)
//                    .append("\r\nAli系统判定结果：图片属于 ").append(aliContentCheckService.getLabelMsg(checkResult.getLabel()))
//                    .append(",").append(aliContentCheckService.getSuggestionMsg(checkResult.getSuggestion()))
//                    .append(",概率是").append(checkResult.getRate())
                    .append("\r\nTencent系统判定结果：图片审核结论是 ").append(tencentImageCheckService.getSuggestionMsg(pornResult.getSuggestion()))
                    .append(",概率是").append(pornResult.getConfidence())
                    .append("\r\n判定时间：").append(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));

            String opUrl = "https://{hostname}/tz-live-video/liveRoom/adminKickingUser/{userId}?sign={sign}";
            opUrl = opUrl.replace("{hostname}", hostname).replace("{userId}", String.valueOf(userId));
            String sign = UUID.randomUUID().toString() + RandomStringUtils.randomNumeric(8);
            opUrl = opUrl.replace("{sign}", sign);
            emailMsg.append("\r\n点击此链接【将此用户踢出房间】：").append(opUrl);

            String signKey = RedisKeyConst.getAdminKickingUserSignKey(userId);
            redisTemplate.opsForValue().set(signKey, sign, 2, TimeUnit.DAYS);
            redisTemplate.opsForValue().set(alertTime, new Date(), 10, TimeUnit.MINUTES);

            emailService.sendEmail("同桌连麦图片检测结果需要人工判定", emailMsg.toString());
        });

    }


}
